package com.azunitech.apm.bundles.processors;

import java.util.*;
import java.io.*;
import java.net.*;

import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

public class SocketDispatcher implements EventHandler
{
     private Collection<OutputStreamWriter>   clients = new LinkedList<OutputStreamWriter>();
     private String          port    = "9999";
     private ServerSocket listenerSocket;
     private Thread       listenerThread;
 
     public void setPort( String port)  { this.port = port; }
     private String  getPort()          { return this.port; }
      
     public void activateOptions()
     {   
    	 try {   
    		 listenerSocket  = new ServerSocket( Integer.parseInt(port) );
             listenerThread  = new Thread() {   
            	 public void run() {   
            		 try {   
            			 Socket clientSocket;    
                         while( (clientSocket = listenerSocket.accept()) != null ) {   
                             synchronized( clients ) {
                            	 clients.add( new OutputStreamWriter(clientSocket.getOutputStream()) );
                             }
                         }
                     }
                     catch( SocketException e ) {
                    	 // Normal close operation. Doing nothing
                         // terminates the thread gracefully.
                     }
                     catch( IOException e ) {
                    	 // Other IO errors also kill the thread, but with
                         // a logged message.
                     }
                 }
             };
             listenerThread.setDaemon( true );
             listenerThread.start();
         }
         catch( IOException e ) {
        	 System.out.println(e.getMessage());
         }
     }
 
     public synchronized void append( String event ) {   
         // If this Appender has been closed or if there are no
         // clients to service, just return.
 
         if( listenerSocket== null || clients.size() <= 0 )
             return;
  
  
          String message = event;
  
          synchronized( clients ) {   
        	  for( Iterator i = clients.iterator(); i.hasNext(); ) {
        		  Writer out = (Writer)( i.next() );
                  try {
                	  out.write( message, 0, message.length() );
                      out.flush();
                  }
                  catch( IOException e ) {
                	  i.remove();         // because the connection is closed.    
                  }
              }
          }
      }
  
      public synchronized void close() {
    	  try {   
              if( listenerSocket == null ) 
                  return;
              listenerSocket.close();  
  
              for( Iterator i = clients.iterator(); i.hasNext(); ) {
            	  ((Writer) i.next()).close();
                  i.remove();
              }
  
              listenerThread.join(); 
              listenerThread  = null;   
              listenerSocket  = null; 
              clients         = null;
          }
          catch( Exception e ){
            	 System.out.println(e.getMessage());
          }
      }
      
      public void handleEvent(Event event) {
    	  String[] propNames = event.getPropertyNames();
    	  StringBuffer buffer = new StringBuffer();
    	  buffer.append("===========================================");
    	  buffer.append("\r\n");
    	  buffer.append("Topic: ");
    	  buffer.append(event.getTopic());
    	  buffer.append("\r\n");
		
    	  for( String name : propNames){
    		  Object obj = event.getProperty(name);
    		  buffer.append(name);
    		  buffer.append(" :");
    		  buffer.append( obj != null? obj.toString(): "");
    		  buffer.append("\r\n");
    	  }
    	  this.append(buffer.toString());
      }
  }
